package com.hbpa.pan.web.exception;

import com.hbpa.pan.core.exception.RPanBusinessException;
import com.hbpa.pan.core.exception.RPanFrameworkException;
import com.hbpa.pan.core.response.ResponseCode;
import com.hbpa.pan.core.response.ResponseEntity;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.Optional;

/**
 * @author: BlcakTiger
 * @date: 2023/10/15 15:51
 * @contact: hsf6661@163.com
 * @description: 全局异常处理器
 */
@RestControllerAdvice
public class WebExceptionHandler {

    /**
     * R-Pan业务异常处理器:当应用程序中存在业务错误时，会抛出此异常。
     * @param e 异常对象
     * @return
     */
    @ExceptionHandler(value = RPanBusinessException.class)
    public ResponseEntity rPanBusinessExceptionHandler(RPanBusinessException e){
        return ResponseEntity.fail(e.getCode());
    }

    /**
     * 参数校验方法异常处理器:当验证方法参数时出现错误时，会抛出此异常。
     * @param e 异常对象
     * @return
     */
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public ResponseEntity methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e){
        ObjectError objectError = e.getBindingResult().getAllErrors().stream().findFirst().get();
        return ResponseEntity.fail(ResponseCode.ERROR_PARAM.getCode(),objectError.getDefaultMessage());
    }

    /**
     * 约束违规异常处理器：当应用程序中存在约束违规时，会抛出此异常。
     * @param e
     * @return
     */
    @ExceptionHandler(value = ConstraintViolationException.class)
    public ResponseEntity constraintViolationExceptionHandler(ConstraintViolationException e){
        ConstraintViolation<?> constraintViolation = e.getConstraintViolations().stream().findFirst().get();
        return ResponseEntity.fail(ResponseCode.ERROR_PARAM.getCode(),constraintViolation.getMessage());
    }

    /**
     * servlet请求参数丢失异常处理器：当请求参数缺失时，会抛出此异常。
     * @param e
     * @return
     */
    @ExceptionHandler(value = MissingServletRequestParameterException.class)
    public ResponseEntity missingServletRequestParamterExceptionHandler(MissingServletRequestParameterException e){
        return ResponseEntity.fail(ResponseCode.ERROR_PARAM.getCode());
    }

    /**
     * 非法状态异常处理器：当调用方法的状态不合法或不适当时，会抛出此异常。
     * @param e
     * @return
     */
    @ExceptionHandler(value = IllegalStateException.class)
    public ResponseEntity illegalStateExceptionHandler(IllegalStateException e){
        return ResponseEntity.fail(ResponseCode.ERROR_PARAM.getCode());
    }

    /**
     * 绑定异常处理器：当绑定对象时出现错误时，会抛出此异常。
     * @param e
     * @return
     */
    @ExceptionHandler(value = BindException.class)
    public ResponseEntity bindExceptionHandler(BindException e){
        FieldError fieldError = e.getBindingResult().getFieldErrors().stream().findFirst().get();
        return ResponseEntity.fail(ResponseCode.ERROR_PARAM.getCode(),fieldError.getDefaultMessage());
    }

    /**
     * 运行时异常处理器：当项目运行时出现异常则抛出此异常
     * @param e
     * @return
     */
    @ExceptionHandler(value = RuntimeException.class)
    public ResponseEntity runtimeExceptionHandler(RuntimeException e){
        return ResponseEntity.fail(ResponseCode.ERROR.getCode(),e.getMessage());
    }

    /**
     * 其他框架异常处理器：当项目中集成的其他框架出现异常抛出此异常
     * @param e
     * @return
     */
    @ExceptionHandler(value = RPanFrameworkException.class)
     public ResponseEntity rPanFrameworkException(RPanFrameworkException e){
        return ResponseEntity.fail(ResponseCode.ERROR.getCode(),e.getMessage());
     }
}
